#include "NetworkManager.h"
#include <functional>

namespace SeanNetwork {

NetworkManager::NetworkManager()
    : m_CurrentChannel(ChannelType::KCP),
      m_State(ConnectionState::Disconnected),
      m_ChannelDetectTimerId(0),
      m_Port(0),
      m_KcpConsecutivePacketLoss(0) {
}

NetworkManager::~NetworkManager() {
    Stop();
}

bool NetworkManager::Initialize(const NetworkConfig& config) {
    /* 功能：初始化网络管理器
       参数：config-网络配置
       返回：初始化是否成功 */
    m_Config = config;
    
    // 创建保持io_context运行的work对象
    m_Work = std::make_unique<asio::io_context::work>(m_IoContext);
    
    // 创建定时器管理器
    m_TimerManager = std::make_unique<TimerManager>(m_IoContext);
    
    // 初始化通道
    if (!InitializeChannels()) {
        return false;
    }
    
    return true;
}

bool NetworkManager::Connect(const std::string& host, uint16_t port) {
    /* 功能：连接到远程主机
       参数：host-主机地址，port-端口号
       返回：连接操作是否成功启动 */
    if (m_State == ConnectionState::Connected || m_State == ConnectionState::Connecting) {
        return false;
    }
    
    // 先更新状态为Connecting
    UpdateConnectionState(ConnectionState::Connecting);
    
    m_Host = host;
    m_Port = port;
    m_KcpConsecutivePacketLoss = 0;
    
    bool kcpStarted = false;
    bool tcpStarted = false;
    
    // 优先启动KCP连接
    if (m_KcpChannel) {
        kcpStarted = m_KcpChannel->Connect(host, port);
    }
    
    // 同时启动TCP连接作为备份
    if (m_TcpChannel) {
        tcpStarted = m_TcpChannel->Connect(host, port);
    }

    // 如果任一通道启动连接成功，则返回成功
    return kcpStarted || tcpStarted;
}

void NetworkManager::Disconnect() {
    /* 功能：断开连接 */
    if (m_State == ConnectionState::Disconnected) {
        return;
    }
    
    UpdateConnectionState(ConnectionState::Disconnected);
    
    // 取消通道检测定时器
    if (m_TimerManager && m_ChannelDetectTimerId > 0) {
        m_TimerManager->CancelTimer(m_ChannelDetectTimerId);
        m_ChannelDetectTimerId = 0;
    }
    
    // 断开所有通道连接
    if (m_KcpChannel) {
        m_KcpChannel->Disconnect();
    }
    
    if (m_TcpChannel) {
        m_TcpChannel->Disconnect();
    }
    
    // 清空接收队列
    std::lock_guard<std::mutex> lock(m_ReceiveQueueMutex);
    while (!m_ReceiveQueue.empty()) {
        m_ReceiveQueue.pop();
    }
}

bool NetworkManager::SendMsg(std::shared_ptr<NetworkMessage> message) {
    /* 功能：发送消息
       参数：message-要发送的消息
       返回：发送操作是否成功启动 */
    if (!message || m_State != ConnectionState::Connected) {
        return false;
    }
    
    // 获取当前活动通道
    auto activeChannel = GetActiveChannel();
    if (!activeChannel) {
        return false;
    }
    
    // 通过活动通道发送消息
    return activeChannel->SendMsg(message);
}

void NetworkManager::SetMessageCallback(MessageReceiveCallback callback) {
    m_MessageCallback = callback;
}

void NetworkManager::SetConnectionCallback(ConnectionStateCallback callback) {
    m_ConnectionCallback = callback;
}

ConnectionState NetworkManager::GetConnectionState() const {
    return m_State;
}

ChannelType NetworkManager::GetCurrentChannelType() const {
    return m_CurrentChannel;
}

NetworkStats NetworkManager::GetNetworkStats() {
    auto* activeChannel = GetActiveChannel();
    if (activeChannel) {
        return activeChannel->GetNetworkStats();
    }
    
    return NetworkStats();
}

bool NetworkManager::SwitchChannel(ChannelType channelType) {
    /* 功能：手动切换通道
       参数：channelType-目标通道类型
       返回：切换是否成功 */
    std::lock_guard<std::mutex> lock(m_ChannelMutex);
    
    if (m_CurrentChannel == channelType) {
        return true;  // 已经是目标通道
    }
    
    INetworkChannel* targetChannel = nullptr;
    
    if (channelType == ChannelType::KCP && m_KcpChannel) {
        targetChannel = m_KcpChannel.get();
    }
    else if (channelType == ChannelType::TCP && m_TcpChannel) {
        targetChannel = m_TcpChannel.get();
    }
    
    if (!targetChannel || targetChannel->GetConnectionState() != ConnectionState::Connected) {
        return false;  // 目标通道不可用
    }
    
    // 切换通道
    m_CurrentChannel = channelType;
    return true;
}

bool NetworkManager::Start() {
    /* 功能：启动网络管理器
       返回：启动是否成功 */
    if (m_WorkerThreads.size() > 0) {
        return false;  // 已经启动
    }
    
    // 启动工作线程
    StartWorkerThreads();
    
    // 启动通道状态检测定时器
    if (m_TimerManager) {
        m_ChannelDetectTimerId = m_TimerManager->AddTimer(
            m_Config.ChannelDetectInterval,
            [this]() {
                DetectChannelStatus();
            },
            TimerType::Repeated
        );
    }
    
    return true;
}

void NetworkManager::Stop() {
    /* 功能：停止网络管理器 */
    // 断开连接
    Disconnect();
    
    // 停止工作线程
    StopWorkerThreads();
    
    // 释放资源
    if (m_TimerManager) {
        m_TimerManager->ClearAllTimers();
        m_TimerManager.reset();
    }
    
    m_KcpChannel.reset();
    m_TcpChannel.reset();
}

INetworkChannel* NetworkManager::GetActiveChannel() {
    /* 功能：获取当前活动通道
       返回：活动通道指针，无可用通道返回nullptr */
    std::lock_guard<std::mutex> lock(m_ChannelMutex);
    
    if (m_CurrentChannel == ChannelType::KCP && m_KcpChannel) {
        return m_KcpChannel.get();
    }
    else if (m_CurrentChannel == ChannelType::TCP && m_TcpChannel) {
        return m_TcpChannel.get();
    }
    
    return nullptr;
}

const INetworkChannel* NetworkManager::GetActiveChannel() const {
    /* 功能：获取当前活动通道（const版本）
       返回：活动通道指针，无可用通道返回nullptr */
    if (m_CurrentChannel == ChannelType::KCP && m_KcpChannel) {
        return m_KcpChannel.get();
    }
    else if (m_CurrentChannel == ChannelType::TCP && m_TcpChannel) {
        return m_TcpChannel.get();
    }
    
    return nullptr;
}

INetworkChannel* NetworkManager::GetBackupChannel() {
    /* 功能：获取备用通道
       返回：备用通道指针，无可用备用通道返回nullptr */
    std::lock_guard<std::mutex> lock(m_ChannelMutex);
    
    if (m_CurrentChannel == ChannelType::KCP && m_TcpChannel) {
        return m_TcpChannel.get();
    }
    else if (m_CurrentChannel == ChannelType::TCP && m_KcpChannel) {
        return m_KcpChannel.get();
    }
    
    return nullptr;
}

void NetworkManager::HandleMessageReceived(std::shared_ptr<NetworkMessage> message, ChannelType sourceChannel) {
    /* 功能：处理接收到的消息
       参数：message-接收到的消息，sourceChannel-消息来源通道 */
    if (!message) {
        return;
    }
    
    // 如果消息来自非活动通道，但是需要处理的消息，说明备用通道也正常工作
    if (sourceChannel != m_CurrentChannel) {
        // 可以考虑在此处进行通道质量评估
    }
    
    // 添加到接收队列
    {
        std::lock_guard<std::mutex> lock(m_ReceiveQueueMutex);
        m_ReceiveQueue.push(message);
    }
    
    // 调用消息回调
    if (m_MessageCallback) {
        m_MessageCallback(message);
    }
}

void NetworkManager::HandleConnectionStateChanged(ConnectionState state, const std::string& reason, ChannelType channel) {
    /* 功能：处理通道连接状态变更
       参数：state-新状态，reason-状态变更原因，channel-状态变更的通道 */
    if (channel == m_CurrentChannel) {
        // 主通道状态变更
        if (state == ConnectionState::Connected) {
            UpdateConnectionState(ConnectionState::Connected);
        }
        else if (state == ConnectionState::Disconnected || state == ConnectionState::Failed) {
            // 主通道断开，尝试切换到备用通道
            auto* backupChannel = GetBackupChannel();
            if (backupChannel && backupChannel->GetConnectionState() == ConnectionState::Connected) {
                SwitchChannel(backupChannel->GetChannelType());
                UpdateConnectionState(ConnectionState::Connected, "Switched to backup channel");
            }
            else {
                UpdateConnectionState(state, reason);
            }
        }
    }
    else {
        // 备用通道状态变更，如果主通道不可用，可以考虑切换到备用通道
        if (state == ConnectionState::Connected) {
            auto* activeChannel = GetActiveChannel();
            if (!activeChannel || activeChannel->GetConnectionState() != ConnectionState::Connected) {
                SwitchChannel(channel);
                UpdateConnectionState(ConnectionState::Connected, "Switched to available channel");
            }
        }
    }
}

void NetworkManager::DetectChannelStatus() {
    /* 功能：定时检测通道状态
       处理：检查当前通道质量，必要时切换通道 */
    if (m_State != ConnectionState::Connected) {
        return;
    }
    
    // 检查主通道状态
    auto* activeChannel = GetActiveChannel();
    if (!activeChannel) {
        return;
    }
    
    // 获取通道统计信息
    NetworkStats stats = activeChannel->GetNetworkStats();
    
    bool needSwitch = false;
    std::string switchReason;
    
    /* 通道切换判断逻辑：
       1. 当KCP为当前通道时，如果检测到连续丢包超过阈值或延迟过高，切换到TCP
       2. 当TCP为当前通道时，如果KCP通道正常且性能良好，可以切回KCP */
    if (m_CurrentChannel == ChannelType::KCP) {
        // 检查KCP通道质量
        uint32_t latency = activeChannel->GetLatency();
        
        // 检查是否有丢包
        if (stats.PacketLoss > m_KcpConsecutivePacketLoss) {
            m_KcpConsecutivePacketLoss = static_cast<uint32_t>(stats.PacketLoss);
        }
        
        // 判断是否需要切换
        if (m_KcpConsecutivePacketLoss >= m_Config.KcpMaxPacketLoss) {
            needSwitch = true;
            switchReason = "KCP consecutive packet loss exceeded threshold";
            m_KcpConsecutivePacketLoss = 0;  // 重置计数
        }
        else if (latency >= m_Config.KcpMaxLatency) {
            needSwitch = true;
            switchReason = "KCP latency exceeded threshold";
        }
    }
    else if (m_CurrentChannel == ChannelType::TCP) {
        // 当前是TCP通道，检查KCP通道是否恢复良好
        auto* kcpChannel = m_KcpChannel.get();
        if (kcpChannel && kcpChannel->GetConnectionState() == ConnectionState::Connected) {
            uint32_t kcpLatency = kcpChannel->GetLatency();
            NetworkStats kcpStats = kcpChannel->GetNetworkStats();
            
            // 如果KCP通道状况良好，可以切回KCP
            if (kcpLatency < m_Config.KcpMaxLatency && 
                kcpStats.PacketLoss < m_Config.KcpMaxPacketLoss) {
                needSwitch = true;
                switchReason = "KCP channel recovered, switching back";
            }
        }
    }
    
    // 执行通道切换
    if (needSwitch) {
        HandleChannelSwitch(true);
    }
    
    // 更新通道状态
    if (m_KcpChannel) {
        m_KcpChannel->Update();
    }
    
    if (m_TcpChannel) {
        m_TcpChannel->Update();
    }
}

bool NetworkManager::HandleChannelSwitch(bool forceSwitch) {
    /* 功能：处理通道切换判断逻辑
       参数：forceSwitch-是否强制切换通道
       返回：是否执行了通道切换 */
    if (m_State != ConnectionState::Connected && !forceSwitch) {
        return false;
    }
    
    ChannelType targetChannel = (m_CurrentChannel == ChannelType::KCP) ? 
                                ChannelType::TCP : ChannelType::KCP;
    
    // 获取目标通道
    INetworkChannel* targetChannelPtr = nullptr;
    if (targetChannel == ChannelType::KCP && m_KcpChannel) {
        targetChannelPtr = m_KcpChannel.get();
    }
    else if (targetChannel == ChannelType::TCP && m_TcpChannel) {
        targetChannelPtr = m_TcpChannel.get();
    }
    
    // 检查目标通道是否可用
    if (!targetChannelPtr || targetChannelPtr->GetConnectionState() != ConnectionState::Connected) {
        return false;
    }
    
    // 执行通道切换
    bool switched = SwitchChannel(targetChannel);
    if (switched) {
        // 通道切换成功
        std::string channelName = (targetChannel == ChannelType::KCP) ? "KCP" : "TCP";
        UpdateConnectionState(ConnectionState::Connected, "Switched to " + channelName + " channel");
    }
    
    return switched;
}

void NetworkManager::UpdateConnectionState(ConnectionState newState, const std::string& reason) {
    /* 功能：更新连接状态
       参数：newState-新状态，reason-状态变更原因 */
    if (m_State != newState) {
        m_State = newState;
        
        // 调用连接状态回调
        if (m_ConnectionCallback) {
            m_ConnectionCallback(newState, reason);
        }
    }
}

bool NetworkManager::InitializeChannels() {
    /* 功能：初始化KCP和TCP通道
       返回：初始化是否成功 */
    try {
        // 创建KCP通道
        m_KcpChannel = std::make_unique<KcpChannel>(m_IoContext);
        if (!m_KcpChannel->Initialize()) {
            return false;
        }
        
        // 配置KCP参数
        m_KcpChannel->SetNodelay(m_Config.KcpNodelay, m_Config.KcpInterval, 
                                m_Config.KcpResend, m_Config.KcpNoCongestion);
        m_KcpChannel->SetWindowSize(m_Config.KcpSndWnd, m_Config.KcpRcvWnd);
        m_KcpChannel->SetMtu(m_Config.KcpMtu);
        
        // 设置KCP回调
        m_KcpChannel->SetMessageCallback([this](std::shared_ptr<NetworkMessage> message) {
            HandleMessageReceived(message, ChannelType::KCP);
        });
        
        m_KcpChannel->SetConnectionCallback([this](ConnectionState state, const std::string& reason) {
            HandleConnectionStateChanged(state, reason, ChannelType::KCP);
        });
        
        // 创建TCP通道
        m_TcpChannel = std::make_unique<TcpChannel>(m_IoContext);
        if (!m_TcpChannel->Initialize()) {
            return false;
        }
        
        // 配置TCP参数
        m_TcpChannel->SetKeepAliveInterval(m_Config.TcpKeepAliveInterval);
        
        // 设置TCP回调
        m_TcpChannel->SetMessageCallback([this](std::shared_ptr<NetworkMessage> message) {
            HandleMessageReceived(message, ChannelType::TCP);
        });
        
        m_TcpChannel->SetConnectionCallback([this](ConnectionState state, const std::string& reason) {
            HandleConnectionStateChanged(state, reason, ChannelType::TCP);
        });
        
        return true;
    }
    catch (const std::exception& e) {
        // 初始化失败
        m_KcpChannel.reset();
        m_TcpChannel.reset();
        return false;
    }
}

void NetworkManager::StartWorkerThreads() {
    /* 功能：启动工作线程池
       处理：创建指定数量的工作线程运行io_context */
    StopWorkerThreads();  // 确保先停止已有线程
    
    uint32_t threadCount = m_Config.WorkerThreadCount;
    if (threadCount == 0) {
        threadCount = std::thread::hardware_concurrency();
        if (threadCount == 0) {
            threadCount = 2;  // 默认至少2个线程
        }
    }
    
    for (uint32_t i = 0; i < threadCount; ++i) {
        m_WorkerThreads.emplace_back([this]() {
            /* 线程安全保护区域：
               io_context在多线程环境下执行，通过strand保证回调的线程安全 */
            try {
                m_IoContext.run();
            }
            catch (const std::exception& e) {
                // 线程异常，可以记录日志
            }
        });
    }
}

void NetworkManager::StopWorkerThreads() {
    /* 功能：停止工作线程池 */
    if (m_Work) {
        m_Work.reset();  // 允许io_context自然退出
    }
    
    if (!m_IoContext.stopped()) {
        m_IoContext.stop();  // 强制停止所有操作
    }
    
    for (auto& thread : m_WorkerThreads) {
        if (thread.joinable()) {
            thread.join();
        }
    }
    
    m_WorkerThreads.clear();
    
    // 重置io_context供后续使用
    m_IoContext.restart();
    m_Work = std::make_unique<asio::io_context::work>(m_IoContext);
}

} // namespace SeanNetwork
